package com.nanmeishu.services.user.service;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nanmeishu.infrastructure.redis.util.RedisUtil;
import com.nanmeishu.infrastructure.web.entity.ResponseResult;
import com.nanmeishu.infrastructure.web.util.HttpClientUtil;
import com.nanmeishu.infrastructure.web.util.ResultUtil;
import com.nanmeishu.services.feign.TaleFeign;
import com.nanmeishu.services.feign.TransactionFeign;
import com.nanmeishu.services.user.constant.AllConstant;
import com.nanmeishu.services.user.dto.LoginDto;
import com.nanmeishu.services.user.dto.UpdatePasDto;
import com.nanmeishu.services.user.entity.Friend;
import com.nanmeishu.services.user.entity.User;
import com.nanmeishu.services.user.facade.UserService;
import com.nanmeishu.services.user.mapper.FriendMapper;
import com.nanmeishu.services.user.mapper.UserMapper;
import com.nanmeishu.services.user.vo.CountUserVo;
import com.nanmeishu.services.user.vo.GetUserProgressBarsVo;
import com.nanmeishu.util.DataUtil;
import com.nanmeishu.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import redis.clients.jedis.Jedis;

import javax.servlet.http.HttpServletRequest;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    UserMapper userMapper;

    @Value("${ProgressBars}")
    private String progressBars;

    @Value("${TOKEN.DATE}")
    String TOKEN_DATE;

    @Autowired
    TransactionFeign transactionFeign;

    @Autowired
    TaleFeign taleFeign;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    FriendMapper friendMapper;


    @Override
    public void register(User user) {
        registerVerify(user);
        //判断用户是否合法
        List<User> userVerify = userMapper.selectList(new QueryWrapper<User>().eq("username", user.getUsername()).or().eq("phone", user.getPhone()));
        if (userVerify != null && userVerify.size() > 0) {
            throw new RuntimeException("用户名/手机号已被使用，请重试");
        }
        //注册
        int i = userMapper.insert(user);
        if (i <= 0) {
            throw new RuntimeException("注册失败！请检查数据合理性！");
        }
    }

    //注册接口--数据有效性验证
    private void registerVerify(User user) {
        DataUtil.verifyData(user.getPassword(), "密码/password");
        DataUtil.verifyData(user.getPhone(), "手机号/phone");
        DataUtil.verifyData(user.getUsername(), "用户名/username");
        if (user.getCreateTime() == null) {
            user.setCreateTime(LocalDateTime.now());
        }
        user.setPassword(DataUtil.md5Encrypt(user.getPassword(), AllConstant.getPasMd5()));
    }

    @Override
    public void updateUser(User user, HttpServletRequest request) {
        updateVerify(user, request);
        //判断修改的信息是否合法
        //判断手机号是否重复
        if (user.getPhone() != null) {
            User ifUserByPhone = userMapper.selectOne(new QueryWrapper<User>().eq("phone", user.getPhone()));
            if (ifUserByPhone != null) {
                if (user.getUserId().longValue() != ifUserByPhone.getUserId().longValue()) {
                    throw new RuntimeException("修改的手机号码已存在！");
                }
            }
        }
        //判断身份证是否重复
        if (user.getIdentityCard() != null) {
            User ifUserByIdentityCard = userMapper.selectOne(new QueryWrapper<User>().eq("identity_card", user.getIdentityCard()));
            if (ifUserByIdentityCard != null) {
                if (user.getUserId().longValue() != ifUserByIdentityCard.getUserId().longValue()) {
                    throw new RuntimeException("修改的身份证号已存在！");
                }
            }
        }
        //修改
        int u = userMapper.updateById(user);
        if (u <= 0) {
            throw new RuntimeException("修改出错");
        }
    }

    //修改用户信息数据有效性验证
    private void updateVerify(User user, HttpServletRequest request) {
        String token = request.getHeader("accessToken");
        String userId = JwtUtil.get(token, "userId");
        DataUtil.verifyData(userId, "用户ID/userId");
        user.setUserId(Long.parseLong(userId));
        user.setCreateTime(null);
        user.setPassword(null);
    }

    @Override
    public void updatePas(UpdatePasDto updatePasDto, HttpServletRequest request) {
        updatePasVerify(updatePasDto);
        String token = request.getHeader("accessToken");
        String userId = JwtUtil.get(token, "userId");
        //验证用户信息
        //旧密码
        String formerPas = updatePasDto.getFormerPas();
        //新密码
        String newPas = updatePasDto.getNewPas();
        //手机号
        String phone = updatePasDto.getPhone();
        User userVerify = userMapper.selectOne(new QueryWrapper<User>()
                .eq("password", formerPas)
                .eq("user_id", userId));
        if (userVerify != null && userVerify.getPhone().equals(phone)) {
            //验证成功
            User user = new User();
            user.setUserId(Long.parseLong(userId));
            user.setPassword(newPas);
            int u = userMapper.updateById(user);
            if (u <= 0) {
                throw new RuntimeException("修改出错");
            }
        } else {
            throw new RuntimeException("验证用户信息出错");
        }
    }

    //修改密码数据有效性验证
    private void updatePasVerify(UpdatePasDto updatePasDto) {
        DataUtil.verifyData(updatePasDto.getFormerPas(), "旧密码/formerPas");
        DataUtil.verifyData(updatePasDto.getNewPas(), "新密码/newPas");
        DataUtil.verifyData(updatePasDto.getPhone(), "手机号/phone");
    }

    @Override
    public GetUserProgressBarsVo getUserProgressBars(HttpServletRequest request) {
        GetUserProgressBarsVo getUserProgressBarsVo=new GetUserProgressBarsVo();
        String token = request.getHeader("accessToken");
        String userId = JwtUtil.get(token, "userId");
        User user = userMapper.selectById(userId);
        LocalDate createTime = user.getDateOfBirth();
        LocalDateTime currentLocal = LocalDateTime.now(ZoneId.of(ZoneId.SHORT_IDS.get("CTT")));
        if (createTime == null) {
            throw new RuntimeException("请完善出生日期");
        }
        //人生过去的几年
        int gobyYear = currentLocal.toLocalDate().getYear() - createTime.getYear();
        getUserProgressBarsVo.setGobyYear(gobyYear);
        //吃过几顿饭
        getUserProgressBarsVo.setMeal(gobyYear * 366 * 3);
        long until = createTime.until(currentLocal.toLocalDate(), ChronoUnit.DAYS);
        //度过几个夜晚
        getUserProgressBarsVo.setDay(until);
        //经过几个周末
        getUserProgressBarsVo.setWeekend(Integer.parseInt(String.valueOf(until / 7)));
        //今天已过去几小时
        getUserProgressBarsVo.setCurrentHour(Integer.parseInt(String.valueOf(currentLocal.getMinute() > 31 ? currentLocal.getHour() + 1 : currentLocal.getHour())));
        //本周已经过去几天
        //本周一
        LocalDate with = currentLocal.toLocalDate().with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        getUserProgressBarsVo.setCurrentWeek(currentLocal.getDayOfWeek().getValue());
        //本月过去几天
        getUserProgressBarsVo.setCurrentMonth(currentLocal.getDayOfMonth());
        //今天已过去几天
        getUserProgressBarsVo.setCurrentYear(currentLocal.getDayOfYear());
        //获取今日份鸡汤
        String[] sentence = getSentence();
        getUserProgressBarsVo.setSentence(sentence);
        System.out.println(currentLocal + "===============================================");
        return getUserProgressBarsVo;
    }

    @Override
    public String login(LoginDto loginDto) {
        loginVerify(loginDto);
        String username = loginDto.getUsername();
        String password = loginDto.getPassword();
        //验证登录是否成功
        User user = userMapper.selectOne(new QueryWrapper<User>()
                .eq("username", username)
                .eq("password", password));
        if (user == null) {
            throw new RuntimeException("用户名或者密码出错！");
        }
        //生成token
        String token = JwtUtil.sign(username, user.getUserId().toString());
        if (token != null) {
            //存入redis中
            Jedis jedis = redisUtil.getJedis();
            try {
                jedis.set(token, LocalDateTime.now().plusHours(2).minusMinutes(10).toString());
                jedis.expire(token, Integer.parseInt(TOKEN_DATE) - 60 * 10);
            } finally {
                jedis.close();
            }
            return token;
        } else {
            throw new RuntimeException("系统出错");
        }
    }

    @Override
    public void getBackPas(UpdatePasDto updatePasDto) {
        getBackPasVerify(updatePasDto);
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("phone", updatePasDto.getPhone()));
        if (user == null) {
            throw new RuntimeException("当前手机号未注册");
        }
        user.setPassword(DataUtil.md5Encrypt(updatePasDto.getNewPas(), AllConstant.getPasMd5()));
        int u = userMapper.updateById(user);
        if (u<=0) {
            throw new RuntimeException("出错，请重试！");
        }
    }

    @Override
    public CountUserVo countUser(HttpServletRequest request) {
        CountUserVo countUserVo=new CountUserVo();
        String token = request.getHeader("accessToken");
        String userId = JwtUtil.get(token, "userId");
        //获取好友数量
        int countFrient  = friendMapper.selectCount(new QueryWrapper<Friend>().eq("my_user_id", userId));;
        System.out.println("好友数量：" + countFrient);
        //获取日记数量
        ResponseResult taleResult = taleFeign.countTaleByUserId(userId);
        int countTale = (int) taleResult.getData();
        System.out.println("日记数量：" + countTale);
        //获取事务数量
        ResponseResult transactionResult = transactionFeign.countTransactionByUserId(userId);
        int countTransaction = (int) transactionResult.getData();
        System.out.println("事务数量：" + countTransaction);
        countUserVo.setCountFrient(countFrient);
        countUserVo.setCountTale(countTale);
        countUserVo.setCountTransaction(countTransaction);
        return countUserVo;
    }

    @Override
    public User getUserByToken(HttpServletRequest request) {
        String token = request.getHeader("accessToken");
        String userId = JwtUtil.get(token, "userId");
        return userMapper.selectById(userId);
    }

    //找回密码数据有效性验证
    private void getBackPasVerify(UpdatePasDto updatePasDto) {
        DataUtil.verifyData(updatePasDto.getPhone(), "手机号/phone");
        DataUtil.verifyData(updatePasDto.getNewPas(), "新密码/password");
    }

    //登录接口数据有效性验证
    private void loginVerify(LoginDto loginDto) {
        DataUtil.verifyData(loginDto.getUsername(), "用户名/username");
        DataUtil.verifyData(loginDto.getPassword(), " 密码/password");
    }


    //获取今日份鸡汤
    private String[] getSentence() {
        String[] sentence = new String[2];
        String get = "只会幻想而不行动的人，永远也体会不到收获果实时的喜悦。";
        //Map map = JSON.parseObject(JSON.parseObject(get, Map.class).get("data").toString(), Map.class);
//        while (true) {
//            System.out.println(get);
//            if (get.length() > 25) {
//                get = HttpClientUtil.Get(progressBars);
//                //map = JSON.parseObject(JSON.parseObject(get, Map.class).get("data").toString(), Map.class);
//            } else {
//                break;
//            }
//        }
        sentence[0] = get;
        sentence[1] = "每日一言";
        return sentence;
    }
}
